#include "CaseExplicitDemo.h"
#include <iostream>
#include <map>

using namespace std;

// template<typename T>
class TestJson
{
public:
    TestJson(map<string, int> intMap)
    {
        for (auto it = intMap.begin(); it != intMap.end(); ++it)
        {
            dataMap.insert({it->first, to_string(it->second)});
        }
    }
    TestJson(map<string, string> strMap) : dataMap(strMap) {}

    int intValue(string key)
    {
        if (dataMap.find(key) == dataMap.end())
            return 0;
        return stoi(dataMap[key]);
    }

    string stringValue(string key)
    {
        return dataMap[key];
    }

    string& operator[](const char* key) {
        return dataMap[key];
    }

private:
    map<string, string> dataMap;
};

class TestData
{
    friend ostream &operator<<(ostream &os, const TestData &data);

public:
    // explicit 
    TestData(TestJson testJson) : x(testJson.intValue("x")), y(testJson.intValue("y")) {}

private:
    int x, y;
};

ostream &operator<<(ostream &os, const TestData &data)
{
    os << "TestData(" << data.x << "," << data.y << ")";
    return os;
}

void runCaseExplicitDemo()
{
    map<string, int> intMap = {{"x", 10}, {"y", 20}};
    TestData data1 = TestData(TestJson(intMap));
    cout << data1 << endl;

    map<string, string> strMap = {{"x", "10"}, {"y", "20"}};
    TestData data2 = TestData(TestJson(intMap));
    cout << data2 << endl;

    TestData data3 = TestJson({{"x", 10}, {"y", 20}});
    cout << data3 << endl;

    // 当我们只是想解析一个 JSON 对象时，TestJson 并没有重载输出操作符，此时，依然可以输出，以为 TestJson 会被转换成 TestData处理
    // 这是错误的，我们并不希望这样，这可能导致不可预计的错误，比如如果是参与计算时。明明是 其他对象的JSON数据，不可能被转换为 TestData。
    // 但编码时依旧会当作TestData参与计算了。这就会导致不可预计的后果，需要编写时注意
    TestJson jsonObj({{"x1", "10"}, {"y1", "20"}});
    cout << "错误演示案例，预期一个 TestJson 但却被转换成了 TestData 处理：" << endl;
    cout << "   " << "TestJson(" << jsonObj["x1"] << "," << jsonObj["y1"] << ") != " << jsonObj << endl;
}